import 'dart:convert';
import 'dart:ffi';

import 'package:orginone/dart/base/model.dart';
import 'package:orginone/dart/base/schema.dart';
import 'package:orginone/dart/base/storages/models/asset_creation_config.dart';
import 'package:orginone/dart/core/thing/standard/form.dart';
import 'package:orginone/main.dart';
import 'package:orginone/utils/log/log_util.dart';

import '../../../dart/core/target/base/belong.dart';
import '../../../dart/core/target/innerTeam/department.dart';

class FormTool {
  static Future<dynamic> loadForm(dynamic parentData) async {
    Form form = parentData;
    await form.loadContent();
    XForm xForm = parentData.metadata;
    xForm.fields = form.fields;
    // element.data = getFormData(element.id);
    for (var field in xForm.fields) {
      field.field = await FormTool.initFields(field);
    }
    // parentData.metadata = xForm;
    return parentData;
  }

  ///加载 表单下面的属性
  static Future<List> loadFormDatas(dynamic parentData, int skip, int type) async {
    Form form = parentData;
    //奥集能移动端版本发布群 - 版本更新 - 版本信息属性
    String belongId = form.belongId;
    String relation = form.belongId;
    // String belongId = "535878590114435072";
    // String relation = "535878590114435072";
    // var names = form.metadata.collName!.split('-');
    // String collName =
    //     names.isEmpty ? 'formdata-business' : 'formdata-${names[0]}';
    String collName = form.metadata.collName??(/*'formdata-business' : */'_system-things');

    var params = {};
    Map<String, dynamic> match = {};
    if (null == form.metadata.options?.viewDataRange) {
      match = {"isDeleted": false};//, "belongId": belongId
    } else {
      String? perVal = form.metadata.options?.viewDataRange!.person;
      String dataType = form.target.metadata.typeName!;
      String? compVal = form.metadata.options?.viewDataRange!.company;
      match = "单位" == dataType ? {"isDeleted": false, perVal! : relationCtrl.user!.id} : {"isDeleted": false,  ((null == compVal || compVal.isEmpty) ? "belongId" : compVal):  form.directory.belongId};
    }//, "belongId": belongId
    List<dynamic> filter = [];
    final dataRange = form.metadata.options?.dataRange;
    if (dataRange?.filterExp == null &&
        dataRange?.classifyExp == null &&
        dataRange?.authExp == null) {
      return [];
    }
    //值过滤
    if (dataRange?.filterExp != null) {
      List<dynamic> filterExp = jsonDecode(dataRange?.filterExp ?? '[]');
      filter.addAll(filterExp);
      // LogUtil.e('filterExp 参数');
      // LogUtil.e(filterExp);
    }
    //分类过滤
    if (dataRange?.classifyExp != null) {
      Map<String, dynamic> classifyExp =
          jsonDecode(dataRange?.classifyExp ?? '{}');
      match = {...match, ...classifyExp};
      // LogUtil.e(match);
    }
    //权限过滤
    if (dataRange?.authExp != null) {
      List<XTarget> depts = /*(1 == type) ? relationCtrl.user!.departments.where((element) => element.belongId == relationCtrl.user!.currentSpace.id).toList()
           : */form.target.space!.user!.departments.where((element) => element.belongId == form.target.space!.id).toList();
          // form.target.space!.user!.departments.where((element) => element.belongId == form.target.space!.id).toList();
      // List<IDepartment> depts = relationCtrl.user!.getJoinedDepts(form.target.space!.id);
      List<dynamic> authExp = jsonDecode(dataRange?.authExp
          ?.replaceAll('person', relationCtrl.user!.id)
          .replaceAll('company', form.target.spaceId)
          .replaceAll('dept', depts.isEmpty ? "" : depts.first!.id) ??
          '[]'
      );
      // if (depts.isNotEmpty) {
      //   if (depts.length == 1) {
      //     authExp.addAll(jsonDecode(dataRange?.authExp
      //         ?.replaceAll('person', relationCtrl.user!.id)
      //         .replaceAll('company', form.target.spaceId)
      //         .replaceAll('dept', depts.first!.id) ??
      //         '[]'));
      //   } else {
      //     String extractedMatch = extractMatch(authExp.toString(), 'dept');
      //     var deptExp = [];
      //     for (int i = 0; i < depts.length; i++) {
      //       if (i > 0) {
      //         deptExp.add('or');
      //       }
      //       deptExp.add(extractedMatch.replaceAll('dept', depts[i].id));
      //     }
      //     authExp.addAll(jsonDecode(dataRange?.authExp
      //         ?.replaceAll('person', relationCtrl.user!.id)
      //         .replaceAll('company', form.target.spaceId)
      //         .replaceAll(extractedMatch, deptExp.toString()) ??
      //         '[]'));
      //   }
      // } else {
      //   authExp.addAll(jsonDecode(dataRange?.authExp
      //       ?.replaceAll('person', relationCtrl.user!.id)
      //       .replaceAll('company', form.target.spaceId)
      //       .replaceAll('dept', '') ?? '[]'));
      // }

      List newFilter = [];
      //单个值条件
      if (filter.every((element) => element is String)) {
        newFilter.add(filter);
      } else {
        newFilter.addAll(filter);
      }
      newFilter.add('and');
      //单个值条件
      if (authExp.every((element) => element is String)) {
        newFilter.add(authExp);
      } else {
        newFilter.addAll(authExp);
      }
      // LogUtil.e('authExp 参数');
      // LogUtil.e(authExp);
      // match = {...match, ...authExp};
      // LogUtil.e('newFilter 参数');
      // LogUtil.e(newFilter);
      filter = newFilter;
    }
    params = {
      "belongId": belongId,
      "collName": collName,
      "filter": filter,
      "group": null,
      "options": {
        "match": match, //, "belongId": belongId
      },
      "requireTotalCount": true,
      "searchOperation": "contains",
      "searchValue": null,
      "sort": [
        {'selector': "id", 'desc': false}
      ],
      "skip": skip,
      "take": 10,
      'userData': []
    };
    // LogUtil.e('loadFormDatas 参数');
    // LogUtil.e(form.metadata.options?.toJson());
    XLogUtil.dd(params);
    var res = await kernel.collectionLoad(
      belongId,
      belongId,
      [relation],
      collName,
      params,
    );
    // LoadResult<dynamic> res = await form.loadThing(options);
    XLogUtil.dd('加载表单数据');
    XLogUtil.dd(res.data);

    if (res.success && res.data != null && res.data['data'] != null) {
      List formdatas = [];
      List datas = res.data['data'];
      List<FieldModel> fieds = await form.loadFields();
      for (var i = 0; i < datas.length; i++) {
        var data = datas[i];
        // var fm = assembleData(data, fieds);
        var fm = assembleData(data, fieds);
        List fmModels = fm.map((e) => FieldModel.fromJson(e)).toList();
        XLogUtil.dd(fm[0]['value']);
        formdatas.add(fmModels);
      }
      XLogUtil.i(formdatas.map((e) => e[0].value));
      return formdatas;
    }
    return [];
  }

  static bool isList(var value) {
    return value is Iterable;
  }

  static String extractMatch(String jsonStr, String matchValue) {
    if (jsonStr.contains(matchValue)) {
      var jsonData = jsonDecode(jsonStr);
      String regex = r'^[A-Z][0-9]+$';
      for (var item in jsonData) {
        if (isList(item) == true) {
          if (item.length == 3 && RegExp(regex).hasMatch(item[0]) && item[2] == matchValue) {
              return item.toString();
          } else {
              var result = extractMatch(item, matchValue);
              return result;
          }
        }
      }
      return jsonStr;
    } else {
      return '';
    }
  }

  static List assembleData(
      Map<String, dynamic> formCellInfo, List<FieldModel> fiedModels) {
    List datas = [];
    var info = formCellInfo;
    for (var fs in fiedModels) {
      if (info.containsKey(fs.code)) {
        var v = info[fs.code];
        //如果value是字典项 或者分类项 需要去lookup取对应值

        FiledLookup? lookup = fs.lookups?.firstWhere(
          (e) => v == e.value,
          orElse: () => FiledLookup(),
        );
        if (lookup != null && lookup.id != null) {
          v = getFullText(lookup, fs.lookups);
          // LogUtil.e(lookup.toJson());
        }
        fs.value = v.toString();
      }
      // LogUtil.e("assembleData");

      datas.add(fs.toJson());
    }
    // LogUtil.e(fiedModels.length);
    // LogUtil.e("formCellInfo");
    // LogUtil.e(formCellInfo);
    // LogUtil.e("assembleData");
    // LogUtil.d(datas[0]['value']);
    return datas;
  }

  static String getFullText(FiledLookup lookup, List<FiledLookup>? lookups) {
    String? currentName = lookup.text;
    String? parentId = lookup.parentId;
    while (parentId != null) {
      FiledLookup? lookup = lookups?.firstWhere(
        (e) => parentId == e.id,
        orElse: () => FiledLookup(),
      );
      if (lookup != null && lookup.id != null) {
        currentName = '${lookup.text!}/$currentName';
        parentId = lookup.parentId;
        // LogUtil.e(currentName);
      }
    }
    return currentName ?? '';
  }

  static Future<bool> loadMainFieldData(
      FieldModel field, Map<String, dynamic> data) async {
    var value = data[field.id];
    if (value == null) {
      return false;
    }

    await buildField(field, value);
    return true;
  }

  static Future<List<List<String>>> loadSubFieldData(
      XForm form, List<FieldModel> fields) async {
    List<List<String>> content = [];
    for (var thing in form.data!.after) {
      List<String> data = [
        // thing.id ?? thing.otherInfo['id'] ?? '',
        // thing.status ?? "",
        // ShareIdSet[thing.creater]?.name ?? "",
      ];
      for (var field in fields) {
        dynamic value = thing.otherInfo[field.id];
        if (value == null) {
          data.add('');
        } else {
          try {
            if (field.name!.contains("是否启用")) {
              XLogUtil.d('');
            }
            data.add(await buildField(field, thing.otherInfo[field.id]));
          } catch (e) {
            XLogUtil.d(e.toString());
          }
        }
      }
      content.add(data);
    }
    return content;
  }

  static Future<String> buildField(FieldModel field, dynamic value) async {
    // LogUtil.d("buildField");
    // LogUtil.d(field.toJson());
    // LogUtil.d(field.field.type);
    // LogUtil.d(value);
    // LogUtil.d(value.runtimeType);
    if (field.field.type == "input") {
      try {
        value = jsonDecode(value.toString());
        if (value is List && value.isEmpty) {
          value = '';
        }
        if (value is Map) {
          value = value.values.first is List
              ? value.values.first.first['name']
              : value;
        }
        field.field.controller!.text = (value ?? "").toString();
        return value.toString();
      } catch (e) {
        // LogUtil.d(jsonDecode(value));
        field.field.controller!.text = (value ?? "").toString();
        return value.toString();
      }
    } else {
      switch (field.field.type) {
        case "selectPerson":
        case "selectDepartment":
        case "selectGroup":
          // field.field.defaultData.value =
          //     relationCtrl.user?.findShareById(value);
          field.field.defaultData.value =
              await relationCtrl.user?.findEntityAsync(value);
          return field.field.defaultData.value.name;
        case "select":
        case 'switch':
          field.field.select = {};
          for (var value in field.lookups ?? []) {
            field.field.select![value.value] = value.text ?? "";
          }
          if (field.field.type == "select") {
            field.field.defaultData.value = {value: field.field.select![value]};
          } else {
            field.field.defaultData.value = value ?? "";
          }
          return field.field.select![value] ?? "";
        case "upload":
          // LogUtil.d("file");

          // LogUtil.d(jsonDecode(value));
          // LogUtil.d(value.runtimeType);
          if (value == null) {
            return '';
          }
          if (value is String) {
            field.field.defaultData.value = value;
            return value;
          }
          return '';
        // LogUtil.d(value);
        // LogUtil.d(value.runtimeType);
        // value = jsonDecode(value);
        // if (value is List && value.isEmpty) {
        //   return '';
        // }

        // value = value is Map
        //     ? value
        //     : value is List && value.isNotEmpty
        //         ? value[0]
        //         : value;
        // var file = field.field.defaultData.value =
        //     value != null ? FileItemModel.fromJson(value) : null;
        // // LogUtil.d(value);
        // // LogUtil.d(value.runtimeType);
        // // LogUtil.d(file);
        // // return field.field.defaultData.value.name ?? '';
        // return file?.name ?? '';
        case "reference":
          value = jsonDecode(value);
          field.field.defaultData.value = value;
          return value['text'] ?? '';
        default:
          field.field.defaultData.value = value;
          if (field.field.type == "selectTimeRange" ||
              field.field.type == "selectDateRange") {
            return field.field.defaultData.value.join("至");
          }
          return value ?? "";
      }
    }
  }

  static Future<Fields> initFields(FieldModel field) async {
    String? type;
    String? router;
    String? regx;
    Map<dynamic, String> select = {};
    Map rule = jsonDecode(field.rule ?? "{}");
    String widget = rule['widget'] ?? "";
    switch (field.valueType) {
      case "描述型":
        type = "input";
        break;
      case "数值型":
        regx = r'[0-9]';
        type = "input";
        break;
      case "选择型":
      case "分类型":
        if (widget == 'switch') {
          type = "switch";
        } else {
          type = "select";
        }
        break;
      case "日期型":
        type = "selectDate";
        break;
      case "时间型":
        if (widget == "dateRange") {
          type = "selectDateRange";
        } else if (widget == "timeRange") {
          type = "selectTimeRange";
        } else {
          type = "selectTime";
        }
        break;
      case "用户型":
        if (widget.isEmpty) {
          type = "selectPerson";
        } else if (widget == 'group') {
          type = "selectGroup";
        } else if (widget == 'dept') {
          type = "selectDepartment";
        }
        break;
      case '附件型':
        type = "upload";
        break;
      case '引用型':
        type = "reference";
        break;
      default:
        type = 'input';
        break;
    }

    return Fields(
      title: field.name,
      type: type,
      code: field.code,
      select: select,
      router: router,
      regx: regx,
      readOnly: true,
    );
  }

  static Future<String> buildFieldValue(FieldModel field) async {
    String? value;

    switch (field.valueType) {
      case "描述型":
        value = field.value;
        break;
      case "数值型":
        value = field.value;
        break;
      case "选择型":
      case "分类型":
        value = field.value;
        break;
      case "日期型":
        value = field.value;
        break;
      case "时间型":
        value = field.value;

        break;
      case "用户型":
        // LogUtil.d("用户id：${field.value}");
        var entity =
            await relationCtrl.user?.findEntityAsync(field.value ?? '');
        value = entity?.name ?? '';

        break;
      case '附件型':
        value = field.value;
        break;
      case '引用型':
        var reference = jsonDecode(field.value ?? "[]");
        if (reference is List && reference.isNotEmpty) {
          value = reference[0]["text"];
        } else {
          value = "";
        }

        break;
      default:
        value = field.value;
        break;
    }

    return value ?? '';
  }

  // static parseFilter(filters dyn) {
  //
  // }

  static Future<List> loadFormData(IBelong comp, Form form) async {
    const params = {
      // 'filter': filters,
      'skip': 0,
      'take': 100,
    };
    var result = await kernel.collectionLoad(
      comp.metadata.id,
      comp.metadata.belongId!,
      comp.relations,
      '_system-things',
      {
        ...params,
        'requireTotalCount': false,
        'group': null,
        'searchValue': null,
        'searchOperation': 'contains',
        'sort': [
          {
            'selector': 'id',
            'desc': false
          }
        ],
        'options': {
          'match': {
            'isDeleted': false
          }
        },
      },
    );
    List formdatas = [];
    if (result.code == 200 && result.data!.isNotEmpty) {
      List datas = result.data['data'];
      List<FieldModel> fieds = await form.loadFields();
      for (var i = 0; i < datas.length; i++) {
        var data = datas[i];
        // var fm = assembleData(data, fieds);
        var fm = assembleData(data, fieds);
        List fmModels = fm.map((e) => FieldModel.fromJson(e)).toList();
        XLogUtil.dd(fm[0]['value']);
        formdatas.add(fmModels);
      }
      XLogUtil.i(formdatas.map((e) => e[0].value));
      return formdatas;
      // formdatas = result.data["data"];
      // return formdatas;
    } else if (result.code == 200 && result.data!.length == 0) {
      // ToastUtils.showMsg(msg: '${relationCtrl.user..name}中未查到该资产');
    }
    return formdatas;
  }

  static Future<List> loadFormDataById(String id, IBelong entity) async {
    // if (this.company) {
    var result = await kernel.collectionLoad(
      entity!.metadata!.id,
      entity!.metadata!.belongId!,
      entity!.relations,
      '_system-things',
      {
        'requireTotalCount': false,
        'group': null,
        'searchValue': null,
        'searchOperation': 'contains',
        'sort': [
          {
            'selector': 'id',
            'desc': false
          }
        ],
        'options': {
          'match': {
            'id': id,
            'isDeleted': false
          }
        },
      },
    );
    List datas = [];
    if (result.code == 200 && result.data!.isNotEmpty) {
      datas = result.data["data"];
      // List datas = result.data['data'];
      // List<FieldModel> fieds = await form.loadFields();
      // for (var i = 0; i < datas.length; i++) {
      //   var data = datas[i];
      //   // var fm = assembleData(data, fieds);
      //   var fm = assembleData(data, fieds);
      //   List fmModels = fm.map((e) => FieldModel.fromJson(e)).toList();
      //   XLogUtil.dd(fm[0]['value']);
      //   formdatas.add(fmModels);
      // }
      // XLogUtil.i(formdatas.map((e) => e[0].value));
      // return formdatas[0];
      return datas;
    } else if (result.code == 200 && result.data!.length == 0) {
      // ToastUtils.showMsg(msg: '${relationCtrl.user..name}中未查到该资产');
    }
    return datas;
  }

  static Future<Map> getTargetcacheInfo(String id, String belongId, List<String> relations) async {
    var result = await kernel.objectGet(
      id,
      belongId,
      relations,
      'target-cache',
    );
    return result.data;
  }

  static Future<Map> getTops(String id, String belongId, List<String> relations) async {
    var result = await kernel.objectGet(
      id,
      belongId,
      relations,
      'homeConfig',
    );
    return result.data;
  }
}
